package com.aaa.project.commdetail.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.aaa.project.commdetail.domain.TempTimeStatOnlineNew3StatUser;
import com.aaa.project.commdetail.domain.TempTimeStatOnlineNew3StatUserStat;
import com.aaa.project.commdetail.mapper.TempTimeStatOnlineNew3StatUserMapper;
import com.aaa.project.commdetail.mapper.TempTimeStatOnlineNew3StatUserStatMapper;
import com.aaa.project.commdetail.service.TempTimeStatOnlineNew3UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @author baibin
 * @version 1.0
 * @date 2025/4/28 9:19
 * @description TempTimeStatOnlineNew3UserServiceImpl
 */
@Service
public class TempTimeStatOnlineNew3UserServiceImpl implements TempTimeStatOnlineNew3UserService {

    private static final Logger log = LoggerFactory.getLogger(TempTimeStatOnlineNew3UserServiceImpl.class);

    @Resource
    private TempTimeStatOnlineNew3StatUserMapper mapper;
    @Resource
    private TempTimeStatOnlineNew3StatUserStatMapper statMapper;

    @Override
    public void query() {
        log.info("TempTimeStatOnlineNew3UserServiceImpl query");
        // 查询出字段cOline1~96的用户数小于1的数据
        List<TempTimeStatOnlineNew3StatUser> voList = mapper.listOnline1To96StatUser1();
        // 对voList进行分组处理
        Map<String, List<TempTimeStatOnlineNew3StatUser>> voMap =
            voList.stream().collect(Collectors.groupingBy(TempTimeStatOnlineNew3StatUser::getBrasPort));
        // 遍历map
        List<TempTimeStatOnlineNew3StatUserStat> statList = new CopyOnWriteArrayList<>();
        voMap.forEach((k, v) -> {
            // 遍历voList
            List<Date> timeList = new ArrayList<>();
            v.parallelStream().forEach(vo -> {
                // 获取parDay，然后生成前一天和后一天的时间
                DateTime dateTime = DateUtil.parse(vo.getParDay(), "yyyy-MM-dd");
                // 生成前一天的时间
                String previousDay = DateUtil.offsetDay(dateTime, -1).toString("yyyy-MM-dd");
                // 生成后一天的时间
                String nextDay = DateUtil.offsetDay(dateTime, 1).toString("yyyy-MM-dd");

                // 遍历查询cOline1~96的字段，为空的字段跳过，不为空的字段需要结合
                // brasPort、previousDay、nextDay、不为空的cOlineN字段进行查询
                for (int i = 1; i <= 96; i++) {
                    String onlineValue = vo.getOnlineValue(i);
                    if (StrUtil.isBlank(onlineValue)) {
                        continue;
                    }
                    TempTimeStatOnlineNew3StatUser queryVo = new TempTimeStatOnlineNew3StatUser();
                    queryVo.setBrasPort(vo.getBrasPort());
                    queryVo.setOnline(i, queryVo);
                    // 查询前、后一天的数据
                    int count = mapper.count(queryVo, previousDay, nextDay);
                    // 如果有值认为该时间节点不可用，需要保存该字段对应的时间节点
                    if (count > 0) {
                        getTimeList(i, timeList, vo.getParDay());
                    }
                }
            });

            if (CollUtil.isNotEmpty(timeList)) {
                // 解析判断list时间列表是连续时间，格式化输出 "yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mm:ss"
                String dataStr = formatTimeInterval(timeList);
                TempTimeStatOnlineNew3StatUserStat stat = new TempTimeStatOnlineNew3StatUserStat();
                stat.setBrasPort(k);
                stat.setUnusableTime(dataStr);
                log.info("brasPort:{}, timeInterval:{}", k, timeList.size());
                statList.add(stat);
            }
        });
        if (CollUtil.isNotEmpty(statList)) {
            // 批量插入
            statMapper.batchInsert(statList);
        }
    }

    // i = 1~96，计算时间节点区间 从0点开始到24点结束，时间间隔十五分钟，然后跟vo里的parDay日期进行组装，最后存入List><Date>里
    // 然后根据List><Date>里的数据，升序，格式化输出 "yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mm:ss"
    private void getTimeList(int i, List<Date> list, String parDay) {
        if (i < 1 || i > 96) {
            throw new IllegalArgumentException("i must be between 1 and 96");
        }

        // 计算起始时间和结束时间的分钟数
        int startMinutes = (i - 1) * 15;
        int endMinutes = i * 15;

        // 将分钟数转换为时间字符串
        String startTime = formatMinutesToTime(startMinutes);
        String endTime;
        // 处理 i=96 的情况，结束时间为 23:59:59
        if (i == 96) {
            endTime = "23:59:59";
        } else {
            endTime = formatMinutesToTime(endMinutes);
        }

        // 拼接 parDay 和时间字符串
        String startDateTimeStr = parDay + " " + startTime;
        String endDateTimeStr = parDay + " " + endTime;

        // 将字符串转换为 Date 对象
        Date startDateTime = DateUtil.parse(startDateTimeStr, "yyyy-MM-dd HH:mm:ss");
        Date endDateTime = DateUtil.parse(endDateTimeStr, "yyyy-MM-dd HH:mm:ss");
        // 存入 List<Date>
        list.add(startDateTime);
        list.add(endDateTime);
    }

    /**
     * 将分钟数转换为时间字符串
     *
     * @param minutes 分钟数
     * @return 时间字符串，格式为 "HH:mm:ss"
     */
    private String formatMinutesToTime(int minutes) {
        int hours = minutes / 60;
        int mins = minutes % 60;
        return String.format("%02d:%02d:00", hours, mins);
    }

    /**
     * 对 List<Date> 进行升序排序，并格式化输出
     *
     * @param list 存储 Date 对象的列表
     * @return 格式化后的时间区间字符串，格式为 "yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mm:ss"
     */
    private String formatTimeInterval(List<Date> list) {
        // 对时间列表进行排序
        list.sort((o1, o2) -> o1.compareTo(o2));
        // 用于存储连续时间段的起始时间和结束时间
        List<String> continuousPeriods = new ArrayList<>();
        // 遍历时间列表
        Date start = list.get(0); // 当前连续时间段的起始时间
        Date previous = list.get(0); // 上一个时间点

        for (int i = 1; i < list.size(); i++) {
            Date current = list.get(i);
            // 判断当前时间是否与上一个时间连续（差值为15分钟）
            if ((DateUtil.between(previous, current, DateUnit.MINUTE) == 15
                || DateUtil.between(previous, current, DateUnit.MINUTE) == 14) || previous.equals(current)) {
                // 如果连续，更新上一个时间点
                previous = current;
            } else {
                // 如果不连续，记录当前连续时间段
                continuousPeriods.add(DateUtil.format(start, "yyyy-MM-dd HH:mm:ss") + " - " +
                        DateUtil.format(previous, "yyyy-MM-dd HH:mm:ss"));
                // 重置起始时间和上一个时间点
                start = current;
                previous = current;
            }
        }
        // 处理最后一个连续时间段
        continuousPeriods.add(DateUtil.format(start, "yyyy-MM-dd HH:mm:ss") + " - " +
                DateUtil.format(previous, "yyyy-MM-dd HH:mm:ss"));
        // 输出结果\
        return JSONUtil.toJsonStr(continuousPeriods);
    }

}